package com.p2p.base.util;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 合并关联数据集合到主表集合中,把2个集合中的数据合并到一个集合中，通过某个key关联，从而替代数据库的left-join等关联查询。
 * 
 * 方法分3类：合并2个元素为Map的集合、合并2个Map、查找1个Map在另外一个元素为集合的关联Map。
 * 
 * 可选参数：2个map的关联key可能是1个，也可能是2个；合并2个Map时，可以为关联Map的key分别加上前缀prefix，防止重名，也可以不加上。
 * 
 * 不适用场景：多表查询搜索且查询条件在关联表中且需要分页的时候，只使用单表查询+Merge工具，是不够的。
 * @author fansunion@qq.com 2014年11月26日
 */
public class MergeUtil {
	// ///////////////////////合并2个集合中的所有Map/////////////////////

	/**
	 * 合并关联数据集合到主表结合中,把2个集合中的数据合并到一个集合中，通过某个主键关联（不用数据库left join）
	 */
	// 合并2个集合，先查找关联map，再合并2个单独的map，2个map中的关联key是同一个
	public static void merge(List<Map<String, Object>> mainList,
			List<Map<String, Object>> relationList, String relationKey,
			String prefix) {
		int size = mainList.size();
		for (int index = 0; index < size; index++) {
			Map<String, Object> mainMap = mainList.get(index);
			Map<String, Object> relationMap = relationMap(mainMap,
					relationList, relationKey);
			merge(mainMap, relationMap, prefix);
		}
	}

	// 合并2个集合，先查找关联map，再合并2个单独的map，合并map的key加上前缀，2个map中的关联key是2个
	public static void merge(List<Map<String, Object>> mainList,
			String mainKey, List<Map<String, Object>> relationList,
			String relationKey, String prefix) {
		int size = mainList.size();
		for (int index = 0; index < size; index++) {
			Map<String, Object> mainMap = mainList.get(index);
			Map<String, Object> relationMap = relationMap(mainMap, mainKey,
					relationList, relationKey);
			merge(mainMap, relationMap, prefix);
		}
	}

	// 合并2个集合，先查找关联map，再合并2个单独的map，2个map中的关联key是同1个
	public static void merge(List<Map<String, Object>> mainList,
			List<Map<String, Object>> relationList, String relationKey) {
		if (mainList == null || relationList == null) {
			return;
		}
		int size = mainList.size();
		for (int index = 0; index < size; index++) {
			Map<String, Object> mainMap = mainList.get(index);
			Map<String, Object> relationMap = relationMap(mainMap,
					relationList, relationKey);
			merge(mainMap, relationMap);
		}
	}

	// 合并2个集合，2个集合中的map通过key关联
	public static void merge(List<Map<String, Object>> mainList,
			String mainKey, List<Map<String, Object>> relationList,
			String relationKey) {
		if (mainList == null || relationList == null) {
			return;
		}
		int size = mainList.size();
		for (int index = 0; index < size; index++) {
			Map<String, Object> mainMap = mainList.get(index);
			Map<String, Object> relationMap = relationMap(mainMap, mainKey,
					relationList, relationKey);
			merge(mainMap, relationMap);
		}
	}

	// ////////////合并2个Map，前缀prefix可要可不要，不要的情况下，key重名时，会覆盖/////////////////////

	// 合并2个map，relation中的会放到main总，key都加上prefix
	public static void merge(Map<String, Object> mainMap,
			Map<String, Object> relationMap, String prefix) {
		if (mainMap == null || relationMap == null) {
			return;
		}
		Set<Entry<String, Object>> entrySet = relationMap.entrySet();
		for (Map.Entry<String, Object> entry : entrySet) {
			String newKey = prefix + entry.getKey();
			mainMap.put(newKey, entry.getValue());
		}
	}

	// 合并2个map，如果存在重复，relationMap会覆盖main中的
	public static void merge(Map<String, Object> mainMap,
			Map<String, Object> relationMap) {
		if (mainMap == null || relationMap == null) {
			return;
		}
		Set<Entry<String, Object>> entrySet = relationMap.entrySet();
		for (Map.Entry<String, Object> entry : entrySet) {
			if (!mainMap.containsKey(entry.getKey())) {
				mainMap.put(entry.getKey(), entry.getValue());
			}
		}
	}

	// ///////////////////////寻找一个Map在一个集合中的关联Map/////////////////////
	/**
	 * 从一个集合中找到目标对象，如果没有找到，返回null
	 * 
	 * @param 2个map共同的key
	 */
	public static Map<String, Object> relationMap(Map<String, Object> mainMap,
			List<Map<String, Object>> relationMapList, String relationKey) {
		if (mainMap == null || relationMapList == null) {
			return null;
		}
		Object object = mainMap.get(relationKey);
		for (Map<String, Object> map : relationMapList) {
			if (map.get(relationKey).equals(object)) {
				return map;
			}
		}
		return null;
	}

	// 找到1个map在集合list中需要关联的对象,分别指定各自的key
	public static Map<String, Object> relationMap(Map<String, Object> mainMap,
			String mainKey, List<Map<String, Object>> list, String relationKey) {
		if (mainMap == null || list == null) {
			return null;
		}
		Object object = mainMap.get(mainKey);
		for (Map<String, Object> map : list) {
			Object relationObject = map.get(relationKey);
			if (relationObject != null && relationObject.equals(object)) {
				return map;
			}
		}
		return null;
	}
}
